/**
 * 自动 Z-Fighting 修复器
 * 在模型加载时自动检测并修复重面闪烁问题
 */

import * as THREE from '../../lib/three/build/three.module.js';

export class AutoZFightingFixer {
    constructor() {
        this.enabled = true; // 是否启用自动修复
        this.defaultFactor = 0.5; // 默认偏移因子（较小的值，避免过度偏移）
        this.defaultUnits = 0.5;
        this.fixedMeshes = new WeakSet(); // 记录已修复的mesh，避免重复处理
    }

    /**
     * 自动修复加载的模型
     * @param {THREE.Object3D} object3D - 加载的3D对象
     * @param {Object} options - 配置选项
     */
    autoFixModel(object3D, options = {}) {
        if (!this.enabled) return;

        const {
            factor = this.defaultFactor,
            units = this.defaultUnits,
            strategy = 'smart' // 'smart', 'all', 'transparent', 'none'
        } = options;

        let processedCount = 0;

        object3D.traverse((child) => {
            if (child.isMesh && child.material && !this.fixedMeshes.has(child)) {
                const materials = Array.isArray(child.material) ? child.material : [child.material];

                materials.forEach((mat, index) => {
                    const shouldFix = this._shouldFixMaterial(mat, child, strategy);
                    
                    if (shouldFix) {
                        // 根据材质类型和位置智能调整偏移值
                        const { adjustedFactor, adjustedUnits } = this._calculateOffset(
                            mat, child, factor, units, index
                        );

                        mat.polygonOffset = true;
                        mat.polygonOffsetFactor = adjustedFactor;
                        mat.polygonOffsetUnits = adjustedUnits;
                        mat.needsUpdate = true;

                        processedCount++;
                    }
                });

                this.fixedMeshes.add(child);
            }
        });

        if (processedCount > 0) {
            console.log(`🔧 自动修复 Z-Fighting: 处理了 ${processedCount} 个材质`);
        }

        return processedCount;
    }

    /**
     * 判断材质是否需要修复
     */
    _shouldFixMaterial(material, mesh, strategy) {
        switch (strategy) {
            case 'all':
                return true;

            case 'transparent':
                // 只修复透明材质
                return material.transparent === true;

            case 'smart':
                // 智能判断：透明材质、或者是贴花类材质
                if (material.transparent) return true;
                if (material.alphaTest > 0) return true;
                if (mesh.name && (
                    mesh.name.toLowerCase().includes('decal') ||
                    mesh.name.toLowerCase().includes('overlay') ||
                    mesh.name.toLowerCase().includes('sticker')
                )) {
                    return true;
                }
                // 检查材质是否有贴图且不是完全不透明
                if (material.map && material.opacity < 1) return true;
                return false;

            case 'none':
            default:
                return false;
        }
    }

    /**
     * 智能计算偏移值
     * 根据材质属性、mesh位置、层级等因素动态调整
     */
    _calculateOffset(material, mesh, baseFactor, baseUnits, materialIndex) {
        let adjustedFactor = baseFactor;
        let adjustedUnits = baseUnits;

        // 1. 透明材质：轻微向后偏移
        if (material.transparent) {
            adjustedFactor = baseFactor * 1.5;
            adjustedUnits = baseUnits * 1.5;
        }

        // 2. 贴花类材质：向前偏移（显示在表面上）
        if (mesh.name && (
            mesh.name.toLowerCase().includes('decal') ||
            mesh.name.toLowerCase().includes('overlay')
        )) {
            adjustedFactor = -baseFactor * 2;
            adjustedUnits = -baseUnits * 2;
        }

        // 3. 多材质mesh：为每个材质分配不同的偏移值
        if (materialIndex > 0) {
            adjustedFactor += materialIndex * 0.1;
            adjustedUnits += materialIndex * 0.1;
        }

        // 4. 根据mesh的世界位置Y值调整（高度越高，偏移越小）
        const worldPos = new THREE.Vector3();
        mesh.getWorldPosition(worldPos);
        if (worldPos.y > 10) {
            adjustedFactor *= 0.8;
            adjustedUnits *= 0.8;
        }

        return { adjustedFactor, adjustedUnits };
    }

    /**
     * 批量修复场景中的所有对象
     */
    fixEntireScene(scene, options = {}) {
        let totalProcessed = 0;

        scene.traverse((object) => {
            if (object.type === 'Scene') return;
            if (object.isLight || object.isCamera) return;
            if (object.userData?.isGround || object.userData?.isHelper) return;

            const processed = this.autoFixModel(object, options);
            totalProcessed += processed;
        });

        console.log(`✅ 场景全局修复完成: 共处理 ${totalProcessed} 个材质`);
        return totalProcessed;
    }

    /**
     * 移除某个对象的 Z-Fighting 修复
     */
    removeFixFromModel(object3D) {
        let removedCount = 0;

        object3D.traverse((child) => {
            if (child.isMesh && child.material) {
                const materials = Array.isArray(child.material) ? child.material : [child.material];

                materials.forEach(mat => {
                    if (mat.polygonOffset) {
                        mat.polygonOffset = false;
                        mat.polygonOffsetFactor = 0;
                        mat.polygonOffsetUnits = 0;
                        mat.needsUpdate = true;
                        removedCount++;
                    }
                });

                this.fixedMeshes.delete(child);
            }
        });

        if (removedCount > 0) {
            console.log(`🔄 移除 Z-Fighting 修复: 还原了 ${removedCount} 个材质`);
        }

        return removedCount;
    }

    /**
     * 启用自动修复
     */
    enable() {
        this.enabled = true;
        console.log('✅ Z-Fighting 自动修复已启用');
    }

    /**
     * 禁用自动修复
     */
    disable() {
        this.enabled = false;
        console.log('⏸️ Z-Fighting 自动修复已禁用');
    }

    /**
     * 检测场景中的潜在问题
     */
    detectIssues(scene) {
        const issues = [];
        const meshes = [];

        // 收集所有mesh
        scene.traverse((object) => {
            if (object.isMesh) {
                meshes.push(object);
            }
        });

        console.log(`🔍 扫描 ${meshes.length} 个 Mesh...`);

        // 检测重叠或极近的mesh
        for (let i = 0; i < meshes.length; i++) {
            for (let j = i + 1; j < meshes.length; j++) {
                const mesh1 = meshes[i];
                const mesh2 = meshes[j];

                // 跳过地面和辅助对象
                if (mesh1.userData?.isGround || mesh2.userData?.isGround) continue;
                if (mesh1.userData?.isHelper || mesh2.userData?.isHelper) continue;

                // 计算包围盒
                mesh1.geometry.computeBoundingBox();
                mesh2.geometry.computeBoundingBox();

                const box1 = mesh1.geometry.boundingBox.clone();
                const box2 = mesh2.geometry.boundingBox.clone();

                box1.applyMatrix4(mesh1.matrixWorld);
                box2.applyMatrix4(mesh2.matrixWorld);

                // 检查包围盒是否相交
                if (box1.intersectsBox(box2)) {
                    const center1 = new THREE.Vector3();
                    const center2 = new THREE.Vector3();
                    box1.getCenter(center1);
                    box2.getCenter(center2);

                    const distance = center1.distanceTo(center2);
                    const avgSize = (box1.getSize(new THREE.Vector3()).length() + 
                                   box2.getSize(new THREE.Vector3()).length()) / 2;

                    // 如果距离远小于平均尺寸，可能有Z-Fighting
                    if (distance < avgSize * 0.1) {
                        issues.push({
                            mesh1: mesh1.name || `Mesh_${i}`,
                            mesh2: mesh2.name || `Mesh_${j}`,
                            distance: distance.toFixed(4),
                            severity: distance < avgSize * 0.01 ? 'high' : 'medium'
                        });
                    }
                }
            }
        }

        // 输出结果
        if (issues.length > 0) {
            console.log(`⚠️ 发现 ${issues.length} 个潜在的 Z-Fighting 问题：`);
            
            const highSeverity = issues.filter(i => i.severity === 'high');
            const mediumSeverity = issues.filter(i => i.severity === 'medium');

            if (highSeverity.length > 0) {
                console.log(`\n🔴 高风险 (${highSeverity.length} 个):`);
                highSeverity.slice(0, 5).forEach((issue, index) => {
                    console.log(`  ${index + 1}. ${issue.mesh1} ↔ ${issue.mesh2} (距离: ${issue.distance})`);
                });
            }

            if (mediumSeverity.length > 0) {
                console.log(`\n🟡 中风险 (${mediumSeverity.length} 个):`);
                mediumSeverity.slice(0, 5).forEach((issue, index) => {
                    console.log(`  ${index + 1}. ${issue.mesh1} ↔ ${issue.mesh2} (距离: ${issue.distance})`);
                });
            }

            console.log(`\n💡 建议：运行 window.autoFixAllZFighting() 自动修复`);
        } else {
            console.log('✅ 未检测到明显的 Z-Fighting 风险');
        }

        return issues;
    }
}

// 创建全局单例
const autoFixer = new AutoZFightingFixer();

// 暴露到全局
if (typeof window !== 'undefined') {
    window.autoZFightingFixer = autoFixer;

    // 便捷方法
    window.autoFixZFighting = function(object3D, options) {
        return autoFixer.autoFixModel(object3D, options);
    };

    window.autoFixAllZFighting = function(options) {
        if (!window.manager || !window.manager.getCurrentScene()) {
            console.error('❌ 场景未加载');
            return;
        }
        const scene = window.manager.getCurrentScene().scene;
        return autoFixer.fixEntireScene(scene, options);
    };

    window.detectZFightingIssues = function() {
        if (!window.manager || !window.manager.getCurrentScene()) {
            console.error('❌ 场景未加载');
            return;
        }
        const scene = window.manager.getCurrentScene().scene;
        return autoFixer.detectIssues(scene);
    };

    console.log('🤖 自动 Z-Fighting 修复器已加载！');
    console.log('   使用 autoFixAllZFighting() 自动修复整个场景');
    console.log('   使用 detectZFightingIssues() 检测潜在问题');
}

export default autoFixer;



